package cn.miju.admin.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.miju.admin.framework.content.CodeMessage;
import cn.miju.admin.framework.exception.ServiceException;
import cn.miju.admin.system.service.UserService;
import cn.miju.admin.system.vo.*;
import cn.miju.database.constant.DbConstant;
import cn.miju.database.entity.SysRole;
import cn.miju.database.entity.SysUser;
import cn.miju.database.entity.SysUserAuthGroup;
import cn.miju.database.entity.SysUserAuthRole;
import cn.miju.database.mapper.SysUserAuthGroupMapper;
import cn.miju.database.mapper.SysUserAuthRoleMapper;
import cn.miju.database.service.SysUserAuthRoleDataService;
import cn.miju.database.service.SysUserDataService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <pre>
 * 用户
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-31 10:09
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
    private final SysUserDataService sysUserDataService;
    private final SysUserAuthRoleMapper sysUserAuthRoleMapper;
    private final SysUserAuthRoleDataService sysUserAuthRoleDataService;
    private final SysUserAuthGroupMapper sysUserAuthGroupMapper;

    /**
     * 用户分页查询
     * @param inVO {@link UserPageInVO}
     * @return {@link Page<UserPageOutVO>}
     */
    @Override
    public Page<UserPageOutVO> getPage(UserPageInVO inVO) {
        Page<SysUser> sysUserPage;
        if (null == inVO.getGroupId()) {
            LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.lambdaQuery();
            if (StringUtils.isNotBlank(inVO.getKeyword())) {
                queryWrapper.like(SysUser::getAccountNo, inVO.getKeyword());
                queryWrapper.or(childQueryWrapper -> childQueryWrapper.like(SysUser::getUsername, inVO.getKeyword()));
            }
            sysUserPage = sysUserDataService.page(new Page<>(inVO.getPage(), inVO.getPageSize()), queryWrapper);
        } else {
            sysUserPage = sysUserAuthGroupMapper.getUserPageByGroupId(new Page<>(inVO.getPage(), inVO.getGroupId()), inVO.getGroupId());
        }
        Page<UserPageOutVO> page = new Page<>();
        BeanUtil.copyProperties(sysUserPage, page);
        if (CollUtil.isNotEmpty(sysUserPage.getRecords())) {

            page.setRecords(sysUserPage.getRecords().stream().map(sysUser -> {
                UserPageOutVO outVO = new UserPageOutVO();
                BeanUtil.copyProperties(sysUser, outVO);
                outVO.setRegisterTime(sysUser.getCreatedTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                List<SysRole> userRoleList = sysUserAuthRoleMapper.getUserRoleList(sysUser.getId());
                if (CollUtil.isNotEmpty(userRoleList)) {
                    outVO.setRole(userRoleList.stream().map(SysRole::getId).collect(Collectors.toList()));
                    outVO.setRoleName(userRoleList.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")));
                }
                outVO.setGroup(inVO.getGroupId());
                if (null == inVO.getGroupId()) {
                    SysUserAuthGroup sysUserAuthGroup = sysUserAuthGroupMapper.selectOne(Wrappers.<SysUserAuthGroup>lambdaQuery().eq(SysUserAuthGroup::getUserId, sysUser.getId()));
                    if (Objects.nonNull(sysUserAuthGroup)) {
                        outVO.setGroup(sysUserAuthGroup.getGroupId());
                    }
                }
                return outVO;
            }).collect(Collectors.toList()));
        }
        return page;
    }

    /**
     * 保存用户
     * @param inVO {@link UserSaveInVO}
     */
    @Override
    public void save(UserSaveInVO inVO) {
        long userId;
        if (null == inVO.getId()) {
            if (StringUtils.isBlank(inVO.getPassword())) {
                throw new ServiceException("传入密码不能为空");
            }
            SysUser sysUser = SysUser.builder().
                    accountNo(inVO.getAccountNo()).
                    password(inVO.getPassword()).
                    username(inVO.getUsername()).
                    sex(inVO.getSex()).
                    mobile(inVO.getMobile()).
                    email(inVO.getEmail()).
                    build();
            sysUserDataService.save(sysUser);
            userId = sysUser.getId();
        } else {
            sysUserDataService.update(Wrappers.<SysUser>lambdaUpdate().
                    set(SysUser::getAccountNo, inVO.getAccountNo()).
                    set(SysUser::getUsername, inVO.getUsername()).
                    set(SysUser::getSex, inVO.getSex()).
                    set(SysUser::getMobile, inVO.getMobile()).
                    set(SysUser::getEmail, inVO.getEmail()).
                    set(SysUser::getUpdatedTime, LocalDateTime.now()).
                    eq(SysUser::getId, inVO.getId()));
            userId = inVO.getId();
            if (CollUtil.isNotEmpty(inVO.getRole())) {
                sysUserAuthRoleMapper.delete(Wrappers.<SysUserAuthRole>lambdaQuery().eq(SysUserAuthRole::getUserId, userId));
            }
            if (null != inVO.getGroup()) {
                sysUserAuthGroupMapper.delete(Wrappers.<SysUserAuthGroup>lambdaQuery().eq(SysUserAuthGroup::getUserId, userId));
            }
        }
        if (CollUtil.isNotEmpty(inVO.getRole())) {
            List<SysUserAuthRole> sysUserAuthRoleList = Lists.newArrayList();
            inVO.getRole().forEach(roleId -> sysUserAuthRoleList.add(SysUserAuthRole.builder().userId(userId).roleId(roleId).build()));
            sysUserAuthRoleDataService.saveBatch(sysUserAuthRoleList);
        }
        if (null != inVO.getGroup()) {
            sysUserAuthGroupMapper.insert(SysUserAuthGroup.builder().userId(userId).groupId(inVO.getGroup()).build());
        }
    }

    /**
     * 批量删除用户
     * @param inVO {@link UserDeleteInVO}
     */
    @Override
    public void deletes(UserDeleteInVO inVO) {
        sysUserDataService.removeBatchByIds(inVO.getIds());
        sysUserAuthRoleMapper.delete(Wrappers.<SysUserAuthRole>lambdaQuery().in(SysUserAuthRole::getUserId, inVO.getIds()));
        sysUserAuthGroupMapper.delete(Wrappers.<SysUserAuthGroup>lambdaQuery().in(SysUserAuthGroup::getUserId, inVO.getIds()));
    }

    /**
     * 修改账户密码
     * @param inVO {@link UpdatePasswordInVO}
     */
    @Override
    public void updatePassword(UpdatePasswordInVO inVO) {
        SysUser sysUser = inVO.getLoginUser();
        if (!Objects.equals(inVO.getOldPassword(), sysUser.getPassword())) {
            throw new ServiceException(CodeMessage.FAIL.getCode(), "当前密码输入错误！");
        }
        sysUser.setPassword(inVO.getNewPassword());
        sysUser.setUpdatedBy(sysUser.getId());
        sysUser.setUpdatedTime(LocalDateTime.now());
        sysUserDataService.updateById(sysUser);
    }

    /**
     * 修改账户信息
     * @param inVO {@link UpdateAccountInfoInVO}
     */
    @Override
    public void updateAccountInfo(UpdateAccountInfoInVO inVO) {
        SysUser sysUser = inVO.getLoginUser();
        sysUser.setUsername(inVO.getUsername());
        sysUser.setSex(inVO.getSex());
        sysUser.setMobile(inVO.getMobile());
        sysUser.setEmail(inVO.getEmail());
        if (StringUtils.isNotBlank(inVO.getSignature())) {
            sysUser.setSignature(inVO.getSignature());
        }
        sysUser.setUpdatedBy(sysUser.getId());
        sysUser.setUpdatedTime(LocalDateTime.now());
        sysUserDataService.updateById(sysUser);
    }

    /**
     * 重置密码
     * @param inVO {@link ResetPasswordInVO}
     */
    @Override
    public void resetPassword(ResetPasswordInVO inVO) {
        SysUser sysUser = sysUserDataService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getAccountNo, inVO.getAccountNo()));
        if (Objects.isNull(sysUser)) {
            throw new ServiceException("账号不存在，请重新输入！");
        }
        if (DbConstant.SysUserStatus.DISABLE.equals(sysUser.getStatus())) {
            throw new ServiceException("该账号已停用，请联系管理员！");
        }
    }
}
